﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CapaDeDominio;
using CapaDeDatos;

namespace CapaDeNegocio
{
    class AdministracionServiceImpl : IAdministracionService
    {
        #region Dependencias
        ILocalDAO localDAO = null;
        ISalaDAO salaDAO = null;
        IInstrumentoDAO instrumentoDAO = null;
        IReservaDAO reservaDAO = null;
        IServicioDAO servicioDAO = null;
        IClienteDAO clienteDAO = null;
        IMaestraDAO maestraDAO = null;
        IUsuarioDAO usuarioDAO = null;
        #endregion

        #region Operaciones de negocio
        public ICollection<Maestra> ListarMaestrosXTabla(String nomtabla)
        {
            return maestraDAO.ObtenerXNombreTabla(nomtabla);
        }

        public Maestra ObtenerTipoDoc ( int codigo )
        {
            return maestraDAO.Obtener(codigo);
        }

        public Usuario ObtenerUsuario ( int codigo )
        {
            return usuarioDAO.Obtener(codigo);
        }
        #endregion

        #region Métodos de soporte para entidad Local
        public Local ObtenerLocal(int codigo)
        {
            return localDAO.Obtener(codigo);
        }
        public ICollection<Local> ListarLocalesXNombre(String nombre)
        {
            return localDAO.ListarXNombre(nombre);
        }
        public ICollection<Local> ListarLocales()
        {
            return localDAO.ListarTodos();
        }

        #endregion

        #region Métodos de soporte para entidad Instrumento
        public Instrumento RegistrarInstrumento(int tipo, string marca, string modelo, string caracteristicas,
        int aniofabricacion, decimal alquiler)
        {
            // Excepción si falta algún dato requerido
            if (tipo == null || marca == null || modelo == null || aniofabricacion == 0 ||
                caracteristicas == null || alquiler == 0)
                throw new DatosInsuficientesException("Faltan datos para crear un instrumento");
            // Excepción si ya se registró el mismo instrumento (por codigo de instrumento)
            ICollection<Instrumento> InstrumentoEncontrado = instrumentoDAO.ObtenerXCaracteristica(caracteristicas);
            if (InstrumentoEncontrado.Count > 0)
                throw new EntidadRepetidaException("El instrumento ya existe");

            //Creación de Instrumento
            Instrumento instrumentoACrear = new Instrumento();
            instrumentoACrear.Tipo = maestraDAO.Obtener(tipo);
            instrumentoACrear.Marca = marca;
            instrumentoACrear.Modelo = modelo;
            instrumentoACrear.AnioFabricacion = aniofabricacion;
            instrumentoACrear.Caracteristicas = caracteristicas;
            instrumentoACrear.Alquiler = alquiler;
            //instrumentoACrear.Reservas = reservas;
            //instrumentoACrear.Salas = salas;
            return instrumentoDAO.Crear(instrumentoACrear);

        }
        public ICollection<Instrumento> ListarInstrumentos(int tipo, string marca, string modelo, int? aniofabricacion,
        string caracteristicas, decimal alquiler, ICollection<Reserva> reservas, ICollection<Sala> salas)
        {
            //Instrumento codigoExistente = null;
            //if (codigo != null || codigo != 0)
            //  codigoExistente = instrumentoDAO.Obtener(codigo.Value);
            //return instrumentoDAO.ListarXBusqueda(
            //  null, tipo, marca, modelo, aniofabricacion, caracteristicas, alquiler, reservas, salas);
            return null;
        }

        public Instrumento ObtenerInstrumento(int codigo)
        {
            return instrumentoDAO.Obtener(codigo);
        }
        public ICollection<Instrumento> ListarInstrumentos()
        {
            return instrumentoDAO.ListarTodos();
        }

        #endregion

        #region Métodos de soporte para entidad Sala
        public void ArmarSala(int codigoSala, decimal alquiler, ICollection<Instrumento> instrumentosBasicos, ICollection<Servicio> serviciosAdicionales)
        {
            Sala sala = salaDAO.Obtener(codigoSala);
            //Excepcion Mensaje de error si se intenta ingresar más instrumentos que la capacidad de la sala.
            if ((instrumentosBasicos.Count) >= sala.Capacidad)
                throw new CapacidadMaximaException("La cantidad de Instrumento excede a la capacidad de la sala");

            //Excepcion Mensaje de error si se intenta ingresar más de 2 guitarras/1 batería/1 teclado/2 micrófonos (configuración básica).
            int cantidadGuitarras = 0;
            int cantidadBateria = 0;
            int cantidadTeclado = 0;
            int cantidadMicrofonos = 0;

            foreach (Instrumento instrumento in instrumentosBasicos)
            {
                switch (instrumento.Tipo.codigo_tabla)
                {
                    case 1://Guitarra
                        cantidadGuitarras += 1;
                        if (cantidadGuitarras > 2)
                            throw new CantidadTipoInstrumentoException("La cantidad de guitarras no debe exceder de 2");
                        break;
                    case 2://Bateria
                        cantidadBateria += 1;
                        if (cantidadBateria > 1)
                            throw new CantidadTipoInstrumentoException("La cantidad de baterias no debe exceder de 1");
                        break;
                    case 3://Teclado
                        cantidadTeclado += 1;
                        if (cantidadTeclado > 1)
                            throw new CantidadTipoInstrumentoException("La cantidad de teclados no debe exceder de 1");
                        break;
                    case 4://Microfono
                        cantidadMicrofonos += 1;
                        if (cantidadMicrofonos > 2)
                            throw new CantidadTipoInstrumentoException("La cantidad de micrófonos no debe exceder de 2");
                        break;
                    default:
                        break;
                }
            }
            //Se actualiza el costo de la sala
            salaDAO.ActualizarCosto(codigoSala, alquiler);
            //Se asigna los instrumentos basico a la sala
            if (instrumentosBasicos != null)
                salaDAO.AsignarInstrumentos(codigoSala, instrumentosBasicos);
            //Se asigna los servicios adicionales a la sala
            if (serviciosAdicionales != null)
                salaDAO.AsignarServicios(codigoSala, serviciosAdicionales);
        }
        public Sala InscribirSala(string nombre, int localCodigo,
            int capacidad, string caracteristicas)
        {
            if (nombre == null || localCodigo == 0 ||
                capacidad == 0 || caracteristicas == null)
                throw new DatosInsuficientesException("Faltan datos para crear la sala");
            // Excepción si ya se registró la misma sala (por nombre y código de local)
            Local localExistente = localDAO.Obtener(localCodigo);
            ICollection<Sala> salasEncontradas = salaDAO.ListarXBusqueda(
                null, nombre, null, null, localExistente, null);
            if (salasEncontradas.Count > 0)
                throw new EntidadRepetidaException("La sala ya existe");
            // Creación de la sala
            Sala salaACrear = new Sala();
            salaACrear.Nombre = nombre;
            salaACrear.Local = localExistente;
            salaACrear.Capacidad = capacidad;
            salaACrear.Caracteristicas = caracteristicas;
            return salaDAO.Crear(salaACrear);
        }
        public ICollection<Sala> ListarSalas(string nombre, int? localCodigo,
            int? capacidad, string caracteristicas)
        {
            Local objLocal = localDAO.Obtener(localCodigo.GetValueOrDefault(0));
            return salaDAO.ListarXBusqueda(null, nombre, caracteristicas, capacidad, objLocal, "");
        }
        public ICollection<Sala> ListarXFiltros(string nombre, Local local, int Guitarras, bool teclado, int capacidad, Servicio servicioGrab)
        {
            return salaDAO.ListarXFiltros(nombre, local, Guitarras, teclado, capacidad, servicioGrab);
        }

        public ICollection<Sala> ListarXBusqueda(int? codigo, string nombre, string caracteristicas, int? capacidad, Local local, string comentarios)
        {
            return salaDAO.ListarXBusqueda(codigo, nombre, caracteristicas, capacidad, local, comentarios);
        }

        #endregion

        #region Métodos de soporte para entidad Reserva
        public ICollection<Reserva> ListarSalasReservadasXFechaHora(DateTime fecha, int hora)
        {
            return reservaDAO.ListarSalasReservadasXFechaHora(fecha, hora);
        }

        public void AsignarInstrumentoAdicionalReserva(int codigo, ICollection<Instrumento> instrumento)
        {
            reservaDAO.AsignarInstrumentos(codigo, instrumento);
        }

        public void AsignarServicioAdicionalReserva(int codigo, ICollection<Servicio> servicio)
        {
            reservaDAO.AsignarServicios(codigo, servicio);
        }

        public Reserva RegistrarReserva(Reserva ReservaACrear)
        {
            return reservaDAO.Crear(ReservaACrear);
        }

        public ICollection<Reserva> ConsultaReserva(DateTime fechaReserva, Sala sala)
        {
            return reservaDAO.ListarXBusquedaReserva(fechaReserva, sala);
        }

        public void AsignarInstrumentosAdicionalReserva(int codigo, ICollection<Instrumento> instrumentos)
        {
            reservaDAO.AsignarInstrumentos(codigo, instrumentos);
        }

        public void AsignarServiciosAdicionalReserva(int codigo, ICollection<Servicio> servicios)
        {
            reservaDAO.AsignarServicios(codigo, servicios);
        }


        #endregion

        #region Métodos de soporte para entidad Cliente
        public Cliente RegistrarCliente(string nombres, string apellidos, int tip_documento, string nro_documento, string correo, DateTime fec_nacimiento, string clave, string clave_validacion, string estado)
        {
            //Mensaje de error si no se ingresa alguno de los datos.
            if (nombres == null || apellidos == null ||
                tip_documento == 0 || nro_documento == null ||
                correo == null || fec_nacimiento == null || estado == null ||
                clave == null || clave_validacion == null)
                throw new DatosInsuficientesException("Faltan datos para crear el cliente");

            //Mensaje de error si los ingresos de clave no coinciden.
            ICollection<Cliente> ClienteEncontrados = null;
            if (!clave.Equals(clave_validacion))
                throw new ClaveNoCoincideException("La clave insertada no coincide.");

            //Mensaje de error si ya se registró previamente el mismo documento de identidad o email.
            ClienteEncontrados = clienteDAO.ListarxFiltros(maestraDAO.Obtener(tip_documento), nro_documento, null);
            if (ClienteEncontrados.Count > 0)
                throw new DatosRepetidoException("Ya existe el cliente con el mismo documento de identidad.");
            ClienteEncontrados = clienteDAO.ListarxFiltros(null, null, correo);
            if (ClienteEncontrados.Count > 0)
                throw new DatosRepetidoException("Ya existe el cliente con el mismo correo.");

            // Creación de cliente
            Cliente clienteaCrear = new Cliente();
            clienteaCrear.Nombres = nombres;
            clienteaCrear.Apellidos = apellidos;
            clienteaCrear.Tip_Documento = maestraDAO.Obtener(tip_documento);
            clienteaCrear.Nro_Documento = nro_documento;
            clienteaCrear.Correo = correo;
            clienteaCrear.Fec_Nacimiento = fec_nacimiento.Date;
            clienteaCrear.Estado = estado;
            clienteaCrear.Usuario = new Usuario() { User = correo, Clave = clave, EsAdministrador = false };
            return clienteDAO.Crear(clienteaCrear);
        }
         //lista de clientes
        public ICollection<Cliente> ListarCLientes()
       
        {
            return clienteDAO.ListarTodos();
        }

        public Cliente ObtenerCliente ( int codigo )
        {
            return clienteDAO.Obtener(codigo);
        }


        #endregion

        #region Métodos de soporte para entidad Servicio
        public Servicio RegistrarServicio(string nombre, string descripcion, decimal alquiler)
        {
            //Mensaje de error si la descripción ya fue ingresada.
            ICollection<Servicio> servicioEncontrados = servicioDAO.ListarXBusqueda(nombre, null, null);
            if (servicioEncontrados.Count > 0)
                throw new DescripcionRepetidaException("La descripción del servicio ya existe.");

            // Creación del Servicio
            Servicio servicioACrear = new Servicio();
            servicioACrear.Nombre = nombre;
            servicioACrear.Descripcion = descripcion;
            servicioACrear.Alquiler = alquiler;
            servicioACrear.Estado = "A";
            servicioACrear.Nombre = nombre;
            return servicioDAO.Crear(servicioACrear);
        }
        public ICollection<Servicio> ListarServicios()
        {
            return servicioDAO.ListarTodos();
        }
        public Servicio ObtenerServicio(int codigo)
        {
            return servicioDAO.Obtener(codigo);
        }
        #endregion


        #region IAdministracionService Members


        public Local CrearLocal(Local localACrear)
        {
            throw new NotImplementedException();
        }

        public Local ModificarLocal(Local localAModificar)
        {
            throw new NotImplementedException();
        }

        public void EliminarLocal(Local localAEliminar)
        {
            throw new NotImplementedException();
        }

        public Instrumento ModificarInstrumento(Instrumento instrumentoAModificar)
        {
            throw new NotImplementedException();
        }

        public void EliminarInstrumento(Instrumento instrumentoAEliminar)
        {
            throw new NotImplementedException();
        }

        #endregion


        #region IAdministracionService Members


        public ICollection<Cliente> ListarClientes ( )
        {
            return clienteDAO.ListarTodos();
        }

        #endregion


        #region IAdministracionService Members


        public Sala ObtenerSala(int codigo)
        {
            return salaDAO.Obtener(codigo);
        }

        #endregion

        #region IAdministracionService Members


        #endregion

        #region IAdministracionService Members

        public Reserva ObtenerReserva(int codigo)
        {
            return reservaDAO.Obtener(codigo);
        }

        #endregion



        #region IAdministracionService Members


        public Usuario ValidaLogin(string usuario, string clave)
        {
            return usuarioDAO.VerificarCorreoContrasena(usuario, clave);
        }

        #endregion
    }
}


